<!--
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-02-10 13:30:47
 * @Description  : 部门选择器
-->

<template>
  <n-tree-select
    class="my-dep-select"
    v-model:value="value"
    filterable
    placeholder="选择部门"
    :options="options"
    :multiple="multiple"
    :render-label="renderLabel"
    :render-tag="multiple ? renderMultipleSelectTag : renderTagSinger"
    @update:value="handleValueChange"
    :on-load="handleLoad"
    :allow-checking-not-loaded="true"
  ></n-tree-select>
</template>

<script setup lang="ts">
import type { VNodeChild } from 'vue'
import type { SelectRenderTag, TreeSelectOption } from 'naive-ui'
import useDepStore from '@/stores/modules/department'
import { getDepartmentByPage, getUserDepartmentByPage } from '@/api/department'
import type { IndexObj } from '@/types/commom'
import { flattenArrayByChildren, arrayToTree } from '@/utils'
import { renderDepLabel, renderTag } from '@/utils/commonBusiness'

const depStore = useDepStore()

// 默认选中的部门ID数组
const props = withDefaults(
  defineProps<{
    defaultDepIds?: string[]
    defaultDepId?: string
    multiple?: boolean
    rootDep?: IndexObj
  }>(),
  {
    defaultDeps: () => [],
    multiple: true,
    rootDep: () => ({
      id: '1',
      pid: '-1'
    })
  }
)

const emits = defineEmits<{
  (e: 'changeValue', value: string | string[], depInfo: IndexObj[]): void
}>()

// 将选中项交给当前组件进行管理（？ 为什么不直接绑定到当前select选择器呢？）
// 希望它功能更加强大，1-defaultDeps可选，需要默认值时，可传递
// 2-不需要默认值时，value发送变化会触发事件，发给父组件
watch(
  props,
  (newValue) => {
    if (newValue.multiple) {
      if (newValue.defaultDepIds) {
        value.value = newValue.defaultDepIds || []
      }
    } else {
      if (newValue.defaultDepId) {
        value.value = newValue.defaultDepId || ''
      }
    }
  },
  {
    deep: true
  }
)

const value = ref<string | string[]>([])

const options = ref<IndexObj[]>([])

const flatOptions = computed(() => {
  return flattenArrayByChildren(options.value)
})

const renderMultipleSelectTag: SelectRenderTag = ({ option, handleClose }) => {
  return renderTag(option, handleClose, () => renderDepLabel(option))
}

const renderTagSinger: SelectRenderTag = ({ option, handleClose }) => {
  return renderDepLabel(option)
}

const renderLabel = (info: {
  option: TreeSelectOption
  checked: boolean
  selected: boolean
}): VNodeChild => {
  return renderDepLabel(info.option)
}

// 加载根部门数组
const initOptions = async () => {
  if (!depStore.fullDepList.length) {
    await depStore.getFullDepList()
  }

  // const res = await getDepartmentByPage({
  //   page: 1,
  //   pageSize: 999,
  //   pid: props.rootDepId
  // })
  // options.value = res.data.items.map((item) => {
  //   return {
  //     ...item,
  //     label: item.name,
  //     key: item.id,
  //     isLeaf: !!item.isLeaf
  //   }
  // })

  // options.value = arrayToTree(
  //   depStore.fullDepList,
  //   'pid',
  //   props.rootDep.pid
  // ).filter((item) => item.id === props.rootDep.id)

  options.value = depStore.fullDepList

  props.defaultDepIds && (value.value = props.defaultDepIds)

  props.defaultDepId && (value.value = props.defaultDepId)
}

// 部门选择项发送改变，触发事件
const handleValueChange = (value: string | string[], option: IndexObj) => {
  // console.log(value, option, 'dep-select')

  let newValue: string[] | string = []
  if (typeof value === 'string') {
    newValue = option ? option.id : ''
  } else {
    newValue = option
      .filter((v: IndexObj) => !!v)
      .map((item: IndexObj) => item.id)
  }

  // // 新增的项，depList中，newValue选中的，且之前没有被选中的
  // let newTargetList = flatOptions.value.filter((item) => {
  //   return (
  //     newValue.includes(item.id) &&
  //     !props?.defaultDepIds.some((item3: any) => item3 === item.id)
  //   )
  // })

  // // 原有的项concat新增的
  // newTargetList = props.defaultDepIds
  //   .filter((item: any) => newValue.includes(item.id))
  //   .concat(newTargetList)

  // 这里只返回了选中的部门数组ID，如果想返回更多的信息，可以使用第二参数
  const depsInfo = flatOptions.value.filter((item) => {
    return newValue.includes(item.id)
  })
  emits('changeValue', newValue, depsInfo)
}

// 有children进行加载
const handleLoad = (option: TreeSelectOption) => {
  return new Promise<void>((resolve) => {
    // 加载部门下的用户，加载部门下的子部门
    Promise.all([
      getUserDepartmentByPage({
        page: 1,
        pageSize: 999,
        pid: option.id as string
      })
    ])
      .then(([res1]) => {
        const newDeps = res1.data.items.map((item) => {
          return {
            ...item,
            key: item.id,
            label: item.name,
            isLeaf: !!item.isLeaf,
            isDep: true
          }
        })

        option.children = [...newDeps]
        if (!option.children.length) {
          option.isLeaf = true
        }
      })
      .finally(() => {
        resolve()
      })
  })
}

onMounted(() => {
  initOptions()
})
</script>

<style scoped lang="scss">
.my-dep-select {
  :deep(.n-base-selection-placeholder__inner) {
    font-size: 13px;
  }
}
</style>
